package com.umessage.hotel.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.SortedMap;
import java.util.TreeMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.riversoft.weixin.pay.base.PaySetting;
import com.riversoft.weixin.pay.payment.Payments;
import com.riversoft.weixin.pay.payment.bean.UnifiedOrderRequest;
import com.riversoft.weixin.pay.payment.bean.UnifiedOrderResponse;
import com.riversoft.weixin.pay.util.SignatureUtil;
import com.umessage.common.service.impl.BaseService;
import com.umessage.common.util.Atools;
import com.umessage.hotel.dao.DepositOrderMapper;
import com.umessage.hotel.dao.MemberInfoMapper;
import com.umessage.hotel.domain.Coupon;
import com.umessage.hotel.domain.DepositOrder;
import com.umessage.hotel.domain.MemberInfo;
import com.umessage.hotel.domain.WxCfg;
import com.umessage.hotel.model.PaySignModel;
import com.umessage.hotel.service.CouponService;
import com.umessage.hotel.service.DepositOrderService;
import com.umessage.hotel.service.WxCfgService;

@Service("depositOrderService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DepositOrderServiceImpl extends BaseService<DepositOrder> implements DepositOrderService {

	@Autowired
	private MemberInfoMapper memberInfoMapper;

	@Autowired
	private CouponService couponService;

	@Autowired
	private WxCfgService wxCfgService;
	
	@Autowired
	private DepositOrderMapper depositOrderMapper;

	/**
	 * 保存充值订单
	 * 
	 * @param hotelId  酒店id
	 * @param memberId 会员id
	 * @param couponId 礼金券id
	 * @param money    充值金额
	 * @return
	 */
	@Override
	public DepositOrder saveDepositOrder(String hotelId, String memberId, Integer couponId, BigDecimal money) {
		BigDecimal payMoney = BigDecimal.ZERO;
		BigDecimal first = BigDecimal.ZERO;
		BigDecimal second = BigDecimal.ZERO;

		if (couponId != null) {
			//TODO:查询条件需要限制酒店id
			Coupon coupon = couponService.selectByKey(couponId);
			// 礼金券类型为充值优惠
			if (coupon != null && coupon.getCouponType().equals("2")) {
				payMoney = BigDecimal.valueOf(coupon.getFirstNumber());
				first = BigDecimal.valueOf(coupon.getFirstNumber());
				second = BigDecimal.valueOf(coupon.getSecondNumber());
			} else {
				throw new RuntimeException("无效的礼金券id");
			}
		}

		if (couponId == null && money != null) {
			payMoney = money;
			first = money;
		}

		DepositOrder depositOrder = new DepositOrder();
		depositOrder.setHotelId(hotelId);
		depositOrder.setMemberId(memberId);
		depositOrder.setDepositId(Atools.getOneStr());
		depositOrder.setCouponId(couponId);
		depositOrder.setPayMoney(payMoney);
		depositOrder.setRealMoney(first);
		depositOrder.setVirtMoney(second);
		depositOrder.setPayStatus("0");
		depositOrder.setAddTime(new Date());
		save(depositOrder);
		return depositOrder;
	}

	/**
	 * 创建统一订单 充值优惠券
	 * 
	 * @param openid    openid
	 * @param orderType 订单类型（订房、充值）
	 * @param orderId   订单id
	 * @param productId 产品id
	 * @param createdIp 创建ip
	 * @param notifyUrl 通知地址
	 * @param fee       支付金额
	 * @return
	 */
	public PaySignModel createUnifiedOrder(String wxcfgid, String openid, String orderType, String orderId,
			Integer productId, String createdIp, String notifyUrl, BigDecimal fee) {

		WxCfg wxCfg = wxCfgService.selectByKey(wxcfgid);

		if (wxCfg != null) {
			PaySignModel signModel = new PaySignModel();

			PaySetting set = new PaySetting();
			set.setAppId(wxCfg.getAppId());
			set.setMchId(wxCfg.getMchId());
			set.setKey(wxCfg.getAppkey());
			set.setCertPath(wxCfg.getApiclientCert());
			set.setCertPassword(wxCfg.getMchId());

			Payments pay = Payments.with(set);
			UnifiedOrderRequest req = new UnifiedOrderRequest();
			req.setBody(orderType);
			req.setTradeNumber(orderId);
//			req.setTotalFee(fee.multiply(BigDecimal.valueOf(100)).intValue());// 分转换为元   *100
			req.setTotalFee(1);//测试阶段为1分
			req.setBillCreatedIp(createdIp);
			req.setNotifyUrl(notifyUrl);
			req.setTradeType("JSAPI");// NATIVE
			req.setProductId(productId != null ? productId.toString() : "");
			req.setOpenId(openid);

			UnifiedOrderResponse resp = pay.unifiedOrder(req);

			SortedMap<String, Object> generals = new TreeMap<>();
			generals.put("appId", wxCfg.getAppId());
			generals.put("nonceStr", Atools.getOneKeyS());
			generals.put("package", "prepay_id=" + resp.getPrepayId());
			generals.put("signType", "MD5");
			generals.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));

			String sign = SignatureUtil.sign(generals, set.getKey());

			signModel.setAppId((String) generals.get("appId"));
			signModel.setTimeStamp((String) generals.get("timeStamp"));
			signModel.setNonceStr((String) generals.get("nonceStr"));
			signModel.setPackage((String) generals.get("package"));
			signModel.setSignType("MD5");
			signModel.setPaySign(sign);
			return signModel;
		}
		return null;
	}

	/**
	 * 会员充值
	 */
	@Override
	@Transactional
	public void depositMemberAccount(String depositId) {

		DepositOrder order = selectByKey(depositId);
		// 未付款订单，避免重复充值
		if (order != null && "0".equals(order.getPayStatus())) {
			MemberInfo memberInfo = memberInfoMapper.getMemberInfoForUpdate(order.getMemberId());
			memberInfo.setRealMoney(memberInfo.getRealMoney().add(order.getRealMoney()));
			memberInfo.setVirtMoney(memberInfo.getVirtMoney().add(order.getVirtMoney()));
			memberInfoMapper.updateByPrimaryKey(memberInfo);
			// 更新订单状态
			order.setPayStatus("1");
			order.setPayTime(new Date());
			updateAll(order);
		}

	}

	@Override
	public BigDecimal countDepositOrderRechargeAmount(String hotelId,
			String startTime, String endTime) {
		return depositOrderMapper.countDepositOrderRechargeAmount(hotelId, startTime, endTime);
	}

	@Override
	public BigDecimal countDepositOrderVirtMoney(String hotelId,
			String startTime, String endTime) {
		return depositOrderMapper.countDepositOrderVirtMoney(hotelId, startTime, endTime);
	}

	/**
	 * 查询充值总金额
	 */
	@Override
	public BigDecimal taotalPay(String hotelId, String startTime, String endTime) {
		return depositOrderMapper.taotalPay( hotelId,  startTime,  endTime);
	}

}
